////////////////////////////////////////////////////////////////////////////////
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
////////////////////////////////////////////////////////////////////////////////

// Public Headers
#include <windows.h>
#include <wsdapi.h>
#include <stdio.h>
#include <strsafe.h>

// Sample Headers
#include "SimpleThermostat_WSD.h"
#include "SimpleThermostat_WSDProxy.h"
#include "CWSDSimpleThermostatProxy.h"

//------------------------------------------------------------------------------
// CreateCWSDSimpleThermostatProxy
//      This is essentially the factory method for the CWSDSimpleThermostatProxy
//      class. It takes a property store that's expected to have come from
//      an FD Function Instance.
//------------------------------------------------------------------------------
HRESULT CreateCWSDSimpleThermostatProxy(
    IPropertyStore* pPropertyStore,
    ISimpleThermostat** ppSimpleThermostat
    )
{
    HRESULT                     hr                          = S_OK;
    PROPVARIANT                 pv                          = {0};
    WCHAR                       szProxyAddress[MAX_PATH]    = {0};
    UUID                        uuid                        = {0};
    CSimpleThermostat_WSDProxy* pCSimpleThermostat_WSDProxy = NULL;
    CWSDSimpleThermostatProxy*  pCWSDSimpleThermostatProxy  = NULL;

    if( NULL == pPropertyStore ||
        NULL == ppSimpleThermostat )
    {
        return E_INVALIDARG;
    }

    wprintf( L"GetValue of PKEY_PNPX_GlobalIdentity (device host id)..." );
    hr = pPropertyStore->GetValue( PKEY_PNPX_GlobalIdentity, &pv );
    wprintf( L"0x%x\n", hr );

    if( S_OK == hr )
    {
        wprintf( L"Device Host ID: %s\n", pv.pwszVal );
    }

    //
    // Create a unique proxy ID to use when connecting to the thermostat device
    //
    if( S_OK == hr )
    {
        hr = UuidCreate( &uuid );
        if( S_OK == hr )
        {
            hr = StringCbPrintfW(
                szProxyAddress, sizeof(szProxyAddress),
                L"urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
                uuid.Data1, uuid.Data2, uuid.Data3,
                uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3],
                uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]);
        }
    }

    //
    // Create the proxy object that implements ISimpleThermostat_WSD.
    // The object being created here is what CWSDSimpleThermostatProxy
    // wraps to expose the real ISimpleThermostat interface.
    // This function being called here was generated by WSD Code Gen.
    //
    if( S_OK == hr )
    {
        wprintf( L"Calling CreateCSimpleThermostat_WSDProxy..." );
        hr = CreateCSimpleThermostat_WSDProxy(
            pv.pwszVal,
            szProxyAddress,
            &pCSimpleThermostat_WSDProxy,
            NULL
            );
        wprintf( L"0x%x\n", hr );
    }

    //
    // Now create the CWSDSimpleThermostatProxy object and hand it
    // the CSimpleThermostat_WSDProxy object.
    //
    if( S_OK == hr )
    {
        wprintf( L"Creating the CWSDSimpleThermostatProxy object..." );
        pCWSDSimpleThermostatProxy =  new CWSDSimpleThermostatProxy(
            pCSimpleThermostat_WSDProxy
            );
        if( NULL == pCWSDSimpleThermostatProxy )
        {
            hr = E_OUTOFMEMORY;
        }
        wprintf( L"0x%x\n", hr );
    }

    if( S_OK == hr )
    {
        *ppSimpleThermostat = static_cast<ISimpleThermostat*>(pCWSDSimpleThermostatProxy);
    }

    //
    // Cleanup
    //
    PropVariantClear( &pv );

    if( NULL != pCSimpleThermostat_WSDProxy )
    {
        pCSimpleThermostat_WSDProxy->Release();
        pCSimpleThermostat_WSDProxy = NULL;
    }

    return hr;
}// CreateCWSDSimpleThermostatProxy


//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::CWSDSimpleThermostatProxy (Constructor)
//------------------------------------------------------------------------------
CWSDSimpleThermostatProxy::CWSDSimpleThermostatProxy(
    ISimpleThermostat_WSD* pSimpleThermostat_WSD
    ):
    m_cRef(1)
{
    pSimpleThermostat_WSD->AddRef();
    m_pSimpleThermostat_WSD = pSimpleThermostat_WSD;
}


//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::~CWSDSimpleThermostatProxy (Destructor)
//------------------------------------------------------------------------------
CWSDSimpleThermostatProxy::~CWSDSimpleThermostatProxy()
{
    if( NULL != m_pSimpleThermostat_WSD )
    {
        m_pSimpleThermostat_WSD->Release();
        m_pSimpleThermostat_WSD = NULL;
    }
}


//
// ISimpleThermostat
//

//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::GetCurrentTemp
//------------------------------------------------------------------------------
HRESULT CWSDSimpleThermostatProxy::GetCurrentTemp(
    LONG* plTemp
    )
{
    return m_pSimpleThermostat_WSD->GetCurrentTemp( plTemp );
}// CWSDSimpleThermostatProxy::GetCurrentTemp


//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::GetDesiredTemp
//------------------------------------------------------------------------------
HRESULT CWSDSimpleThermostatProxy::GetDesiredTemp(
    LONG* plTemp
    )
{
    return m_pSimpleThermostat_WSD->GetDesiredTemp( plTemp );
}// CWSDSimpleThermostatProxy::GetDesiredTemp


//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::SetDesiredTemp
//------------------------------------------------------------------------------
HRESULT CWSDSimpleThermostatProxy::SetDesiredTemp(
    LONG lTemp
    )
{
    return m_pSimpleThermostat_WSD->SetDesiredTemp( lTemp );
}// CWSDSimpleThermostatProxy::SetDesiredTemp


//
// IUnknown
//

//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::QueryInterface
//------------------------------------------------------------------------------
HRESULT CWSDSimpleThermostatProxy::QueryInterface(
    REFIID riid, 
    void** ppvObject
    )
{
    HRESULT hr = S_OK;

    if( NULL == ppvObject )
    {
        return E_INVALIDARG;
    }

    *ppvObject = NULL;

    if( __uuidof(ISimpleThermostat) == riid )
    {
        *ppvObject = static_cast<ISimpleThermostat*>(this);
        AddRef();
    }
    else if( __uuidof(IUnknown) == riid )
    {
        *ppvObject = static_cast<IUnknown*>(this);
        AddRef();
    }
    else
    {
        hr = E_NOINTERFACE;
    }

    return hr;
}// CWSDSimpleThermostatProxy::QueryInterface


//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::AddRef
//------------------------------------------------------------------------------
ULONG CWSDSimpleThermostatProxy::AddRef()
{
    return InterlockedIncrement( &m_cRef );
}// CWSDSimpleThermostatProxy::AddRef


//------------------------------------------------------------------------------
// CWSDSimpleThermostatProxy::Release
//------------------------------------------------------------------------------
ULONG CWSDSimpleThermostatProxy::Release()
{
    LONG lRef = InterlockedDecrement( &m_cRef );

    if( 0 == lRef )
    {
        delete this;
    }
    return lRef;
}// CWSDSimpleThermostatProxy::Release
